﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using IPC.Communication.Framework.BasicFramework;
using IPC.Communication.Framework.Core;

namespace IPC.Communication.Framework.Profinet.LSIS.Helper
{
    public class XGBCnetHelper
    {
        public static string GetErrorText(int err)
        {
            switch (err)
            {
                case 3:
                    return StringResources.Language.LsisCnet0003;
                case 4:
                    return StringResources.Language.LsisCnet0004;
                case 7:
                    return StringResources.Language.LsisCnet0007;
                case 17:
                    return StringResources.Language.LsisCnet0011;
                case 144:
                    return StringResources.Language.LsisCnet0090;
                case 400:
                    return StringResources.Language.LsisCnet0190;
                case 656:
                    return StringResources.Language.LsisCnet0290;
                case 4402:
                    return StringResources.Language.LsisCnet1132;
                case 4658:
                    return StringResources.Language.LsisCnet1232;
                case 4660:
                    return StringResources.Language.LsisCnet1234;
                case 4914:
                    return StringResources.Language.LsisCnet1332;
                case 5170:
                    return StringResources.Language.LsisCnet1432;
                case 28978:
                    return StringResources.Language.LsisCnet7132;
                default:
                    return StringResources.Language.UnknownError;
            }
        }

        public static OperateResult<byte[]> UnpackResponseContent(byte[] send, byte[] response)
        {
            try
            {
                if (response[0] == 6)
                {
                    if (response[3] == 87 || response[3] == 119)
                    {
                        return OperateResult.CreateSuccessResult(response);
                    }
                    string @string = Encoding.ASCII.GetString(response, 4, 2);
                    if (@string == "SS")
                    {
                        int num = Convert.ToInt32(Encoding.ASCII.GetString(response, 6, 2), 16);
                        int num2 = 8;
                        List<byte> list = new List<byte>();
                        for (int i = 0; i < num; i++)
                        {
                            int num3 = Convert.ToInt32(Encoding.ASCII.GetString(response, num2, 2), 16);
                            list.AddRange(Encoding.ASCII.GetString(response, num2 + 2, num3 * 2).ToHexBytes());
                            num2 += 2 + num3 * 2;
                        }
                        return OperateResult.CreateSuccessResult(list.ToArray());
                    }
                    if (@string == "SB")
                    {
                        int num4 = Convert.ToInt32(Encoding.ASCII.GetString(response, 8, 2), 16);
                        byte[] value = Encoding.ASCII.GetString(response, 10, num4 * 2).ToHexBytes();
                        return OperateResult.CreateSuccessResult(value);
                    }
                    return new OperateResult<byte[]>(1, "Command Wrong:" + @string + Environment.NewLine + "Source: " + response.ToHexString());
                }
                if (response[0] == 21)
                {
                    int err = Convert.ToInt32(Encoding.ASCII.GetString(response, 6, 4), 16);
                    return new OperateResult<byte[]>(err, GetErrorText(err));
                }
                return new OperateResult<byte[]>(response[0], "Source: " + SoftBasic.GetAsciiStringRender(response));
            }
            catch (Exception ex)
            {
                return new OperateResult<byte[]>(1, "Wrong:" + ex.Message + Environment.NewLine + "Source: " + response.ToHexString());
            }
        }

        public static int CalculateAddressStarted(string address, bool QI = false)
        {
            if (address.IndexOf('.') < 0)
            {
                return Convert.ToInt32(address);
            }
            string[] array = address.Split('.');
            if (!QI)
            {
                return Convert.ToInt32(array[0]);
            }
            return Convert.ToInt32(array[2]);
        }

        private static bool IsHex(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return false;
            }
            bool result = false;
            for (int i = 0; i < value.Length; i++)
            {
                switch (value[i])
                {
                    case 'A':
                    case 'B':
                    case 'C':
                    case 'D':
                    case 'E':
                    case 'F':
                    case 'a':
                    case 'b':
                    case 'c':
                    case 'd':
                    case 'e':
                    case 'f':
                        result = true;
                        break;
                }
            }
            return result;
        }

        public static OperateResult<string> AnalysisAddress(string address)
        {
            StringBuilder stringBuilder = new StringBuilder();
            try
            {
                stringBuilder.Append("%");
                char[] array = new char[15]
			{
				'P',
				'M',
				'L',
				'K',
				'F',
				'T',
				'C',
				'D',
				'S',
				'Q',
				'I',
				'N',
				'U',
				'Z',
				'R'
			};
                bool flag = false;
                for (int i = 0; i < array.Length; i++)
                {
                    if (array[i] == address[0])
                    {
                        stringBuilder.Append(array[i]);
                        char c = address[1];
                        char c2 = c;
                        if (c2 == 'X')
                        {
                            stringBuilder.Append("X");
                            if (address[0] == 'I' || address[0] == 'Q')
                            {
                                stringBuilder.Append(CalculateAddressStarted(address.Substring(2), QI: true));
                            }
                            else if (IsHex(address.Substring(2)))
                            {
                                stringBuilder.Append(address.Substring(2));
                            }
                            else
                            {
                                stringBuilder.Append(CalculateAddressStarted(address.Substring(2)));
                            }
                        }
                        else
                        {
                            stringBuilder.Append("B");
                            int num = 0;
                            if (address[1] == 'B')
                            {
                                num = CalculateAddressStarted(address.Substring(2));
                                stringBuilder.Append(num);
                            }
                            else if (address[1] == 'W')
                            {
                                num = CalculateAddressStarted(address.Substring(2));
                                stringBuilder.Append(num *= 2);
                            }
                            else if (address[1] == 'D')
                            {
                                num = CalculateAddressStarted(address.Substring(2));
                                stringBuilder.Append(num *= 4);
                            }
                            else if (address[1] == 'L')
                            {
                                num = CalculateAddressStarted(address.Substring(2));
                                stringBuilder.Append(num *= 8);
                            }
                            else if (address[0] == 'I' || address[0] == 'Q')
                            {
                                stringBuilder.Append(CalculateAddressStarted(address.Substring(1), QI: true));
                            }
                            else if (IsHex(address.Substring(1)))
                            {
                                stringBuilder.Append(address.Substring(1));
                            }
                            else
                            {
                                stringBuilder.Append(CalculateAddressStarted(address.Substring(1)));
                            }
                        }
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    throw new Exception(StringResources.Language.NotSupportedDataType);
                }
            }
            catch (Exception ex)
            {
                return new OperateResult<string>(ex.Message);
            }
            return OperateResult.CreateSuccessResult(stringBuilder.ToString());
        }

        public static OperateResult<byte[]> BuildReadByteCommand(byte station, string address, ushort length)
        {
            OperateResult<string> operateResult = AnalysisAddress(address);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(operateResult);
            }
            List<byte> list = new List<byte>();
            list.Add(5);
            list.AddRange(SoftBasic.BuildAsciiBytesFrom(station));
            list.Add(114);
            list.Add(83);
            list.Add(66);
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)operateResult.Content.Length));
            list.AddRange(Encoding.ASCII.GetBytes(operateResult.Content));
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)length));
            list.Add(4);
            int num = 0;
            for (int i = 0; i < list.Count; i++)
            {
                num += list[i];
            }
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)num));
            return OperateResult.CreateSuccessResult(list.ToArray());
        }

        public static OperateResult<byte[]> BuildReadIndividualCommand(byte station, string address)
        {
            return BuildReadIndividualCommand(station, new string[1]
		{
			address
		});
        }

        public static OperateResult<byte[]> BuildReadIndividualCommand(byte station, string[] addresses)
        {
            List<byte> list = new List<byte>();
            list.Add(5);
            list.AddRange(SoftBasic.BuildAsciiBytesFrom(station));
            list.Add(114);
            list.Add(83);
            list.Add(83);
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)addresses.Length));
            if (addresses.Length > 1)
            {
                foreach (string text in addresses)
                {
                    string text2 = text.StartsWith("%") ? text : ("%" + text);
                    list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)text2.Length));
                    list.AddRange(Encoding.ASCII.GetBytes(text2));
                }
            }
            else
            {
                foreach (string address in addresses)
                {
                    OperateResult<string> operateResult = AnalysisAddress(address);
                    if (!operateResult.IsSuccess)
                    {
                        return OperateResult.CreateFailedResult<byte[]>(operateResult);
                    }
                    list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)operateResult.Content.Length));
                    list.AddRange(Encoding.ASCII.GetBytes(operateResult.Content));
                }
            }
            list.Add(4);
            int num = 0;
            for (int k = 0; k < list.Count; k++)
            {
                num += list[k];
            }
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)num));
            return OperateResult.CreateSuccessResult(list.ToArray());
        }

        public static OperateResult<byte[]> BuildReadCommand(byte station, string address, ushort length)
        {
            OperateResult<string> dataTypeToAddress = XGBFastEnet.GetDataTypeToAddress(address);
            if (!dataTypeToAddress.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(dataTypeToAddress);
            }
            switch (dataTypeToAddress.Content)
            {
                case "Bit":
                    return BuildReadIndividualCommand(station, address);
                case "Word":
                case "DWord":
                case "LWord":
                case "Continuous":
                    return BuildReadByteCommand(station, address, length);
                default:
                    return new OperateResult<byte[]>(StringResources.Language.NotSupportedDataType);
            }
        }

        public static OperateResult<byte[]> BuildWriteByteCommand(byte station, string address, byte[] value)
        {
            OperateResult<string> operateResult = AnalysisAddress(address);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(operateResult);
            }
            List<byte> list = new List<byte>();
            list.Add(5);
            list.AddRange(SoftBasic.BuildAsciiBytesFrom(station));
            list.Add(119);
            list.Add(83);
            list.Add(66);
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)operateResult.Content.Length));
            list.AddRange(Encoding.ASCII.GetBytes(operateResult.Content));
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)value.Length));
            list.AddRange(SoftBasic.BytesToAsciiBytes(value));
            list.Add(4);
            int num = 0;
            for (int i = 0; i < list.Count; i++)
            {
                num += list[i];
            }
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)num));
            return OperateResult.CreateSuccessResult(list.ToArray());
        }

        public static OperateResult<byte[]> BuildWriteOneCommand(byte station, string address, byte[] value)
        {
            OperateResult<string> operateResult = AnalysisAddress(address);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(operateResult);
            }
            List<byte> list = new List<byte>();
            list.Add(5);
            list.AddRange(SoftBasic.BuildAsciiBytesFrom(station));
            list.Add(119);
            list.Add(83);
            list.Add(83);
            list.Add(48);
            list.Add(49);
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)operateResult.Content.Length));
            list.AddRange(Encoding.ASCII.GetBytes(operateResult.Content));
            list.AddRange(SoftBasic.BytesToAsciiBytes(value));
            list.Add(4);
            int num = 0;
            for (int i = 0; i < list.Count; i++)
            {
                num += list[i];
            }
            list.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)num));
            return OperateResult.CreateSuccessResult(list.ToArray());
        }

        public static OperateResult<byte[]> BuildWriteCommand(byte station, string address, byte[] value)
        {
            OperateResult<string> dataTypeToAddress = XGBFastEnet.GetDataTypeToAddress(address);
            if (!dataTypeToAddress.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(dataTypeToAddress);
            }
            switch (dataTypeToAddress.Content)
            {
                case "Bit":
                    return BuildWriteOneCommand(station, address, value);
                case "Word":
                case "DWord":
                case "LWord":
                case "Continuous":
                    return BuildWriteByteCommand(station, address, value);
                default:
                    return new OperateResult<byte[]>(StringResources.Language.NotSupportedDataType);
            }
        }

        public static OperateResult<byte[]> Read(IReadWriteDevice plc, int station, string address, ushort length)
        {
            byte station2 = (byte)HslHelper.ExtractParameter(ref address, "s", station);
            OperateResult<byte[]> operateResult = BuildReadCommand(station2, address, length);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            return plc.ReadFromCoreServer(operateResult.Content);
        }

        public static OperateResult<byte[]> Read(IReadWriteDevice plc, int station, string[] address)
        {
            List<string[]> list = SoftBasic.ArraySplitByLength(address, 16);
            List<byte> list2 = new List<byte>(32);
            for (int i = 0; i < list.Count; i++)
            {
                OperateResult<byte[]> operateResult = BuildReadIndividualCommand((byte)station, list[i]);
                if (!operateResult.IsSuccess)
                {
                    return operateResult;
                }
                OperateResult<byte[]> operateResult2 = plc.ReadFromCoreServer(operateResult.Content);
                if (!operateResult2.IsSuccess)
                {
                    return operateResult2;
                }
                list2.AddRange(operateResult2.Content);
            }
            return OperateResult.CreateSuccessResult(list2.ToArray());
        }

        public static OperateResult Write(IReadWriteDevice plc, int station, string address, byte[] value)
        {
            byte station2 = (byte)HslHelper.ExtractParameter(ref address, "s", station);
            OperateResult<byte[]> operateResult = BuildWriteCommand(station2, address, value);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            return plc.ReadFromCoreServer(operateResult.Content);
        }

        public static OperateResult<bool> ReadBool(IReadWriteDevice plc, int station, string address)
        {
            byte station2 = (byte)HslHelper.ExtractParameter(ref address, "s", station);
            OperateResult<byte[]> operateResult = BuildReadIndividualCommand(station2, address);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<bool>(operateResult);
            }
            OperateResult<byte[]> operateResult2 = plc.ReadFromCoreServer(operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return OperateResult.CreateFailedResult<bool>(operateResult2);
            }
            return OperateResult.CreateSuccessResult(SoftBasic.ByteToBoolArray(operateResult2.Content, 1)[0]);
        }

        public static OperateResult Write(IReadWriteDevice plc, int station, string address, bool value)
        {
            byte station2 = (byte)HslHelper.ExtractParameter(ref address, "s", station);
            OperateResult<byte[]> operateResult = BuildWriteOneCommand(station2, address, new byte[1]
		{
			(byte)(value ? 1 : 0)
		});
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            return plc.ReadFromCoreServer(operateResult.Content);
        }

        //[AsyncStateMachine(typeof(<ReadAsync>d__17))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult<byte[]>> ReadAsync(IReadWriteDevice plc, int station, string address, ushort length)
        //{
        //    <ReadAsync>d__17 stateMachine = new <ReadAsync>d__17();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.plc = plc;
        //    stateMachine.station = station;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadAsync>d__18))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult<byte[]>> ReadAsync(IReadWriteDevice plc, int station, string[] address)
        //{
        //    <ReadAsync>d__18 stateMachine = new <ReadAsync>d__18();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.plc = plc;
        //    stateMachine.station = station;
        //    stateMachine.address = address;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__19))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IReadWriteDevice plc, int station, string address, byte[] value)
        //{
        //    <WriteAsync>d__19 stateMachine = new <WriteAsync>d__19();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.plc = plc;
        //    stateMachine.station = station;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadBoolAsync>d__20))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult<bool>> ReadBoolAsync(IReadWriteDevice plc, int station, string address)
        //{
        //    <ReadBoolAsync>d__20 stateMachine = new <ReadBoolAsync>d__20();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<bool>>.Create();
        //    stateMachine.plc = plc;
        //    stateMachine.station = station;
        //    stateMachine.address = address;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__21))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IReadWriteDevice plc, int station, string address, bool value)
        //{
        //    <WriteAsync>d__21 stateMachine = new <WriteAsync>d__21();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.plc = plc;
        //    stateMachine.station = station;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}
    }
}